#include <am.h>

#define DEVICE_BASE 0xa0000000
#define MMIO_BASE   0xa0000000
#define VGACTL_ADDR (DEVICE_BASE + 0x0000100)
#define SYNC_ADDR   0xa0000104

#define FB_ADDR     (MMIO_BASE + 0x1000000)
#define SERIAL_PORT     (DEVICE_BASE + 0x00003f8)

static inline void outb(uintptr_t addr, uint8_t  data) { *(volatile uint8_t  *)addr = data; }

static inline void outl(uintptr_t addr, uint32_t data) { *(volatile uint32_t *)addr = data; }

void __am_gpu_init() {
	volatile int i;
	int w = 400;
	int h = 300;
	uint32_t *fb = (uint32_t *)(uintptr_t)FB_ADDR;
	for(i = 0; i< w*h; i++)
	{
		fb[i] = i;

	}
	volatile uint32_t *sy = (uint32_t *)(uintptr_t)SYNC_ADDR;
	sy[0] = 1;
//	outb(SERIAL_PORT, 'g');
//	outb(SERIAL_PORT, 'p');


	
	outb(0xa0000104,1);
//	outb(SERIAL_PORT, 'u');

}

void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
  *cfg = (AM_GPU_CONFIG_T) {
    .present = true, .has_accel = false,
    .width = 400, .height = 300,
    .vmemsz = 0
  };
}

void __am_gpu_fbdraw(AM_GPU_FBDRAW_T *ctl) {
  if (ctl->sync) {
    outl(SYNC_ADDR, 1);
  }
  int x = ctl->x, y = ctl->y, w = ctl->w, h = ctl->h;
  int a,b;
  uint32_t *myfb = (uint32_t *)(uintptr_t)ctl->pixels;
  uint32_t *fb = (uint32_t *)(uintptr_t)FB_ADDR;
  if (w == 0 || h == 0) return;
  else
  {
    for(a = 0; a < w; a++){
      for(b = 0; b < h; b++){
        fb[x+a+(y+b)*400] = myfb[a+b*w];
      }
    }
  }

}
void __am_gpu_status(AM_GPU_STATUS_T *status) {
  status->ready = true;
}
